package com.wx.network.sever;

import com.wx.exception.RpcStartException;
import com.wx.util.IpUtil;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;

@Slf4j
public class RpcServerSocket {
    private ApplicationContext applicationContext;

    public RpcServerSocket(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public void startRpcServer(int port, int bossGroupThreadNum, int workerGroupThreadNum){
        //创建事件循环组
        NioEventLoopGroup bossGroup = new NioEventLoopGroup(bossGroupThreadNum);
        NioEventLoopGroup workerGroup = new NioEventLoopGroup(workerGroupThreadNum);
        //创建服务端启动器

        ServerBootstrap serverBootstrap = new ServerBootstrap();
        //设置启动属性

        serverBootstrap.group(bossGroup,workerGroup)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG,128)
                .childOption(ChannelOption.SO_KEEPALIVE,Boolean.TRUE)
                .childHandler(new RpcServerHandlerInitialzer(applicationContext)); //业务处理
        //监测端口号是否被使用，如果被使用就加一
        while (IpUtil.isPortBeUse(port)){
            port++;
        }
        final int logPort=port;
        //开始连接
        try {
            ChannelFuture sync = serverBootstrap.bind(port).sync();
            //注册监听器
            sync.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture channelFuture) throws Exception {
                    boolean success = sync.isSuccess();
                    if(success){
                        log.info("rpc服务端启动成功,端口号是:【{}】",logPort);
                    }else {
                            throw new RpcStartException("prc服务端启动失败");
                    }
                }
            });
            ChannelFuture future = sync.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
            log.info("rpc服务端优雅的关闭");
        }
    }
}
